/**
 *******************************************************************************
 * @file  main.c
 * @brief Main program.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2024-08-18       CDT             First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2022, Xiaohua Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by XHSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "main.h"

// 用户引入的系统文件
#include <stdlib.h>
#include <string.h>

#include <ringbuffer.h>
// 用户引入的芯片库文件

// 用户环境头文件
#include "BoardCommunicationModule.h"
#include "BspHelper.h"
#include "BufDef.h"
//#include "EthInitHelper.h"
#include "EepromModule.h"
#include "ExpansionPortModule.h"
#include "I2cCommunicationModule.h"
#include "SdioInitHelper.h"
#include "ResetModule.h"


/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/


/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/
bool run_healthy = true;

rt_thread_t debug_usart_tid;
// i2c4任务，用来收发RTC和温湿度传感器
rt_thread_t rtc_check_tid;
rt_thread_t rtc_flash_tid;
rt_thread_t led_run_tid;
// 串口接收计数监听任务
rt_thread_t usart_transport_check_tid;

/**
* bit0: 是否正常运行
* bit1: 是否在发送数据
*/
uint8_t led_status;
size_t led_busy_times;

// 用来初始化日志缓冲区的锁
extern struct rt_mutex ulog_data_lock;
extern bool ulog_data_lock_inited;

// 线程检查
struct rt_event sys_task_check_event;
/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/
__attribute__((section(".ARM.__at_0x80012900"))) __IO rt_uint8_t test_reg1[512];
char *test_str1 = "hello mem!";
char *test_str2 = "check mem!";
char *test_str3 = "write mem!";

// crc测试数据
uint8_t test_crc_data[] = {0x02, 0x03, 0x00, 0x00, 0x00, 0x02};

rt_thread_t time_test_tid;
/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
// 对时测试线程
void Thread_Time_Flash(void *parmameter) {
  uint32_t e = RT_EOK;
  for (;;) {
    rt_event_recv(&(rtc_ctrl_task.rtc_ctrl_event), (EVENT_EXT_RTC_START_CHECK_TIME_TASK), (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), RT_WAITING_FOREVER, &e);
    sys_time_info.tmp_time_info.year_bcd = 0x25;
    sys_time_info.tmp_time_info.mon_bcd = 0x04;
    sys_time_info.tmp_time_info.day_bcd = 0x24;
    sys_time_info.tmp_time_info.hour_bcd = 0x17;
    sys_time_info.tmp_time_info.min_bcd = 0x10;
    sys_time_info.tmp_time_info.sec_bcd = 0x05;
    sys_time_info.tmp_time_info.update_finished = true;
  }
}

// 调试串口发送函数
void Thread_Usart_Send(void *parmameter) {
  for (;;) {
    if (rt_mq_recv(&debug_usart_mq, debug_usart_tx_buf, sizeof(debug_usart_tx_buf), RT_WAITING_FOREVER) > 0) {
      ;//GPIO_SetPins(LED_ERR_PORT, LED_ERR_PIN);
    }

    {// 控制台DMA发送
      DMA_SetSrcAddr(CM_DMA1, DMA_CH0, (uint32_t) debug_usart_tx_buf);

      DMA_SetTransCount(CM_DMA1, DMA_CH0, rt_strlen(debug_usart_tx_buf));

      (void) DMA_ChCmd(CM_DMA1, DMA_CH0, ENABLE);

      USART_FuncCmd(CM_USART3, USART_TX, ENABLE);
      rt_err_t result = rt_sem_take(debug_usart_sem, 500);
      if (result != RT_EOK) {
        ;//GPIO_SetPins(LED_ERR_PORT, LED_ERR_PIN);
      }
    }// 控制台DMA发送
  }  // 发送循环
}// 调试串口发送函数

// Led运行函数
void Thread_Led_Run(void *parmameter) {
  led_status = 0x01;
  SWDT_FeedDog();

  {
    // 初始引脚状态。取决于初始状态的高低电平哪个是灭
    ;//GPIO_ResetPins(LED_RUN_PORT, LED_RUN_PIN);
    ;//GPIO_ResetPins(LED_ERR_PORT, LED_ERR_PIN);
  }

  for (;;) {
    {                                // 闪烁第一段
      if ((led_status & 0x01) != 0) {// led bsp运行
        ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_0, true);
      }// led bsp运行
    }  // 闪烁第一段
    rt_thread_mdelay(50);

    {// 闪烁第二段
    }// 闪烁第二段
    rt_thread_mdelay(50);

    {// 闪烁第三段
    }// 闪烁第三段
    rt_thread_mdelay(50);

    {// 闪烁第四段
    }// 闪烁第四段
    rt_thread_mdelay(50);

    {// 闪烁第五段
    }// 闪烁第五段
    rt_thread_mdelay(50);

    {                                // 闪烁第六段
      if ((led_status & 0x02) != 0) {// led bsp运行
        ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_0, false);
      }// led bsp运行
    }  // 闪烁第六段
    rt_thread_mdelay(50);

    {// 闪烁第七段
    }// 闪烁第七段
    rt_thread_mdelay(50);

    {// 闪烁第八段
    }// 闪烁第八段
    rt_thread_mdelay(50);

    {// 闪烁第九段
    }// 闪烁第九段
    rt_thread_mdelay(50);

    {// 闪烁第十段
    }// 闪烁第十段
    rt_thread_mdelay(50);

    {                                // 闪烁第十一段
      if ((led_status & 0x02) != 0) {// led bsp运行
        ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_0, true);
      }// led bsp运行
    }  // 闪烁第十一段
    rt_thread_mdelay(50);

    {// 闪烁第十二段
    }// 闪烁第十二段
    rt_thread_mdelay(50);

    {// 闪烁第十三段
    }// 闪烁第十三段
    rt_thread_mdelay(50);

    {// 闪烁第十四段
    }// 闪烁第十四段
    rt_thread_mdelay(50);

    {// 闪烁第十五段
    }// 闪烁第十五段
    rt_thread_mdelay(50);

    {                                // 闪烁第十六段
      if ((led_status & 0x02) != 0) {// led bsp运行
        ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_0, false);
      }// led bsp运行
    }  // 闪烁第十六段
    rt_thread_mdelay(50);

    {// 闪烁第十七段
    }// 闪烁第十七段
    rt_thread_mdelay(50);

    {// 闪烁第十八段
    }// 闪烁第十八段
    rt_thread_mdelay(50);

    {// 闪烁第十九段
    }// 闪烁第十九段
    rt_thread_mdelay(50);

    {// 闪烁第二十段
    }// 闪烁第二十段
    rt_thread_mdelay(50);
    {                          // 对于该清位的地方清位
      if (led_busy_times > 0) {// 处理忙碌状态
        led_busy_times--;
        led_status |= (1 << 1);
      } else {
        led_status &= 0xFD;
      }// 处理忙碌状态

      // 处理网络状态
      //		if (lte_connected == RT_EOK && mqtt1_status == 2) {
      //			led_status |= (1 << 2);
      //			led_status |= (1 << 3);
      //		} else if (lte_connected == RT_EOK && mqtt1_status != 2){
      //			led_status |= (1 << 2);
      //			led_status &= 0xF7;
      //		} else {
      //			led_status &= 0xF3;
      //		}
    }// 对于该清位的地方清位
  }  // 发送循环
}// Led运行函数
char trng_str_buf[24];
uint8_t try_times = 0;
int32_t main_loop(void) {
  // 正常1秒等候， 如果系统不需要外部rtc驱动可以打开这个，关闭秒中断延迟
  //rt_thread_delay(1000);
  // 秒中断延迟。如果系统需要秒中断驱动，则开启这个，以此来激活循环。
  rt_uint32_t e;
  // 半秒中断
  rt_event_recv(&(rtc_ctrl_task.rtc_ctrl_event), (EVENT_EXT_RTC_GET_HALF_SEC_INTC), (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), RT_WAITING_FOREVER, &e);
  ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_0, true);
  ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_1, false);
  eeprom_fram.Write_Eeprom_Bytes(&eeprom_fram, 0x0080, (uint8_t *) trng_str16, 16);
  //ULOG_DEBUG("get tmp: %.02f\n", m_f32Temperature);
  //ULOG_DEBUG("get ms: %d\n", sys_time_info.millisecond);
  if (sys_time_info.millisecond < 495 || sys_time_info.millisecond > 505) {
    try_times++;
    if (try_times > 3) {
			ULOG_ERROR("rtc millisecond error!\n");
      rt_thread_mdelay(1000 - sys_time_info.millisecond);
      __NVIC_SystemReset();
    }
  }
  SWDT_FeedDog();
  // 秒中断
  rt_event_recv(&(rtc_ctrl_task.rtc_ctrl_event), (EVENT_EXT_RTC_GET_SEC_INTC), (RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR), RT_WAITING_FOREVER, &e);
  ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_0, false);
  ch423s_port_ctrl_obj.Write_Port_Sataus(&ch423s_port_ctrl_obj, OUT_PORT_GROUP_1, STATU_OUT_1, true);
  eeprom_fram.Read_Eeprom_Bytes(&eeprom_fram, 0x0080, (uint8_t *) trng_str_buf, 16);
  ULOG_DEBUG("get eeprom trng: %s\n", trng_str_buf);
  //ULOG_DEBUG("get eeprom trng128: %s\n", trng_str);
  //ULOG_DEBUG("get tmp: %.02f\n", m_f32Temperature);
  ULOG_DEBUG("get ms: %d\n", sys_time_info.millisecond);

  // 如果第二次秒中断还是没有对时
  if (rt_tick_get() > 2000 && sys_time_info.time_info.tm_year == 0) {
    rt_event_send(&(rtc_ctrl_task.rtc_ctrl_event), EVENT_EXT_RTC_START_CHECK_TIME_TASK);
  }

  // 检查点事件，当所有事件都发生后才能被激活
  //  rt_event_recv(&(sys_task_check_event),
  //                (
  //                    EVENT_EXT_RTC_GET_SEC_INTC),
  //                (RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR),
  //                RT_WAITING_FOREVER, &e);

  SWDT_FeedDog();

  if (!run_healthy) {
    return 1;
  }


  return 0;
}

/**
 * @brief  Main function of the project
 * @param  None
 * @retval int32_t return value, if needed
 */
int32_t main(void) {
  SWDT_FeedDog();
  // 时间结构体要在所有事情之前初始化，否则会有问题
  Init_Time_Pre_Obj();
  // 系统检查点事件，用来检查是否所有必要任务都已经完成
  rt_event_init(&sys_task_check_event, "sys_task_check_event", RT_IPC_FLAG_PRIO);

  // 初始化crc资源锁
  rt_mutex_init(&crc16_lock, "crc16_lock", RT_IPC_FLAG_PRIO);

  // 扩展IO初始化
  Init_Expansion_Port(&ch423s_port_ctrl_obj, CM_I2C1, "expansion_port");
  // 开启中断通知
  ch423s_port_ctrl_obj.Write_Status_Reg(&ch423s_port_ctrl_obj);

  // 初始化EEPROM
  Init_Eeprom();
	
	// 初始化RESET功能
	//rt_sem_init(&reset_sem, "reset_sem", 0, RT_IPC_FLAG_PRIO);
	//rt_mutex_init(&reset_mutex, "reset_mutex", RT_IPC_FLAG_PRIO);

  // 创建用于发送log的锁
  // 注意，sem不能在main函数被创建前创建。因为对象管理器还没被初始化。
  debug_usart_sem = rt_sem_create("debug_usart", 0, RT_IPC_FLAG_PRIO);
  if (debug_usart_sem == RT_NULL) {
    for (;;) {
      ;// 初始化失败，持续循环
    }
  }
  //创建用于发送log的锁

  // 初始化日志互斥量。负责防止多条日志同时操作一个缓冲区
  if (rt_mutex_init(&ulog_data_lock, "ulog_data_lock", RT_IPC_FLAG_PRIO) != RT_EOK) {
    for (;;) {}
  } else {
    ulog_data_lock_inited = true;
  }

  // 初始化RS485-3运行环境
  Init_Rs485_3_Usart_Env();
  // 用于创建没有接收定时器的串口接收定时信号
  usart_transport_check_sem = rt_sem_create("usart_transport_check_sem", 0, RT_IPC_FLAG_PRIO);
  // 用于创建没有接收定时器的串口接收定时信号
  SWDT_FeedDog();

  // 初始化log发送线程
  debug_usart_tid = rt_thread_create("Thread_Usart_Send",
                                     Thread_Usart_Send, RT_NULL,
                                     THREAD_STACK_SIZE,
                                     THREAD_PRIORITY, THREAD_TIMESLICE);

  if (debug_usart_tid != RT_NULL) {
    rt_thread_startup(debug_usart_tid);
    STATU_SET(sys_status, SYS_LOG_OK);
  }
  SWDT_FeedDog();

  //初始化led闪烁线程
  led_run_tid = rt_thread_create("Thread_Led Run",
                                 Thread_Led_Run, RT_NULL,
                                 THREAD_STACK_SIZE,
                                 THREAD_PRIORITY, THREAD_TIMESLICE);
  if (led_run_tid != RT_NULL) {
    rt_thread_startup(led_run_tid);
  }

  // 初始化串口接收计数任务线程
  usart_transport_check_tid = rt_thread_create("usart_transport_check_tid Run",
                                               Check_Usart_Receive_Data_Task, RT_NULL,
                                               THREAD_STACK_SIZE,
                                               THREAD_PRIORITY, THREAD_TIMESLICE);
  if (usart_transport_check_tid != RT_NULL) {
    rt_thread_startup(usart_transport_check_tid);
  }

  // 任务线程初始化结束

  // 这里需要放到系统初始化之后独立初始化
  //	Lwip_Bsp_Init();
  //	SWDT_FeedDog();

  for (int index = 0; index < CONFIG_ARRAY_SIZE; index++) {
    ULOG_DEBUG("get key: %s, value: %s\n", device_address[index].key, device_address[index].value);
    rt_thread_mdelay(1);
  }
  SWDT_FeedDog();


  // 启动毫秒计数器
  TMR2_Start(CM_TMR2_1, TMR2_CH_A);
  TMR2_Start(CM_TMR2_1, TMR2_CH_B);
  // 启用串口计时器
  //TMR2_Start(CM_TMR2_2, TMR2_CH_A);

  // 等候产生足够多的随机字符串
	ULOG_DEBUG("开始测试随机数");
  rt_thread_mdelay(300);
  memcpy(mqtt_client_id, trng_str, 32);

  // 启动TF卡
  //  SdCard_Config();
  //  SWDT_FeedDog();
  //  int32_t i32EraseRet = SdCard_Erase();
  //  SWDT_FeedDog();
  //  int32_t i32MultiBlockRet = SdCard_RdWrMultiBlock();
  //  SWDT_FeedDog();
  //  if ((LL_OK != i32EraseRet) || (LL_OK != i32MultiBlockRet)) {
  //    /* Test failed */
  //    rt_kprintf("TF test failed!\n");
  //  } else {
  //    /* Test success */
  //    rt_kprintf("TF test successful!\n");
  //  }
  //  SWDT_FeedDog();

  ULOG_DEBUG("get type size: %d\n", sizeof(I2c_Data_Task_Def));

  CRC_CRC16_AccumulateData(CRC_DATA_WIDTH_8BIT, test_crc_data, 6, &crc16_res);
  ULOG_DEBUG("get crc data: 0x%02X%02X\n", crc16_res >> 8, crc16_res & 0xFF);
  en_flag_status_t enCrcMatch = CRC_CRC16_CheckData(0xFFFF, CRC_DATA_WIDTH_8BIT, test_crc_data, 6, crc16_res);

  {// 测试sdram
    BSP_Sdram_GetMemInfo(&m_u32StartAddr, &m_u32ByteSize);
    ULOG_DEBUG("Memory start address: 0x%.8x \n", (unsigned int) m_u32StartAddr);
    ULOG_DEBUG("Memory end   address: 0x%.8x \n", (unsigned int) (m_u32StartAddr + m_u32ByteSize - 1UL));
    ULOG_DEBUG("Memory size  (Bytes): 0x%.8x \n\n", (unsigned int) m_u32ByteSize);
    ULOG_DEBUG("Memory test address: 0x%.8x \n\n", (unsigned int) test_reg1);

    SWDT_FeedDog();
    rt_thread_mdelay(1);


    //char *test_reg1 = rt_mp_alloc(&sdram1_mp, 500);
    //for (int index = 0; index < 3; index++) {
    memset((char *) test_reg1, 0, 512);
    SWDT_FeedDog();
    rt_thread_yield();


    strcpy((char *) test_reg1, "123456");
    rt_thread_mdelay(1);
    ULOG_DEBUG("set mem reg: %s\n", test_reg1);
    rt_thread_mdelay(1);

    //      memcpy((char*)test_reg1, &test_str2, 10);
    //      ULOG_DEBUG("set mem reg: %s\n", test_reg1);
    //      rt_thread_yield();

    //      memcpy((char*)test_reg1, &test_str3, 10);
    //      ULOG_DEBUG("set mem reg: %s\n", test_reg1);
    rt_thread_yield();
    SWDT_FeedDog();
    //}

    //初始化测试数组
    //__attribute__((at(0x80009000))) uint8_t data_array[512];
    //uint8_t *data_array = rt_mp_alloc(&sdram1_mp, 500);
    //    for (int index = 0; index < 512; index++) {
    //      data_array[index] = index;
    //      //SWDT_FeedDog();
    //      rt_thread_yield();
    //    }
    //    uint8_t data_array[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    //    rt_kprintf("read mem data: \nindex: 0x%02X, addr: 0x%08X\n", 0, &(data_array[0]));
    //    uint8_t data_array2[8];
    //    memset(data_array2, 0, 8);
    //    MEMORY_Write8(0x80009000, data_array, 8);
    //    MEMORY_Read8(0x80009000, data_array2, 8);
    //    int index = 0;
    //    //for (int index =0; index<64; index++){
    //    rt_kprintf("read mem data: \nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\nindex: 0x%02X, value: 0x%02X\n",
    //               index * 8, data_array2[index * 8],
    //               index * 8 + 1, data_array2[index * 8 + 1],
    //               index * 8 + 2, data_array2[index * 8 + 2],
    //               index * 8 + 3, data_array2[index * 8 + 3],
    //               index * 8 + 4, data_array2[index * 8 + 4],
    //               index * 8 + 5, data_array2[index * 8 + 5],
    //               index * 8 + 6, data_array2[index * 8 + 6],
    //               index * 8 + 7, data_array2[index * 8 + 7]);
    //    rt_thread_mdelay(1);
    //    SWDT_FeedDog();
    //}

    //uint8_t *ring_buf_data = rt_mp_alloc(&sdram1_mp, 500);
    //    uint8_t ring_buf_data[256];
    //    rt_memset(ring_buf_data, 0, 256);
    //    struct rt_ringbuffer test_rb;
    //    rt_ringbuffer_init(&test_rb, (uint8_t *) ring_buf_data, 256);
    //    char *ring_buf_test1 = "12345ring\n";
    //    uint8_t ring_buf_test2[10];
    //    rt_memcpy(ring_buf_test2, "empty buf\n", 10);
    //    rt_ringbuffer_put_force(&test_rb, (rt_uint8_t *) ring_buf_test1, 10);
    //    rt_kprintf("rnig buf size: %d\n", rt_ringbuffer_data_len(&test_rb));
    //    rt_ringbuffer_get(&test_rb, (rt_uint8_t *) ring_buf_test2, 10);
    //    rt_kprintf((char *) ring_buf_test2);
  }// 测试sdram

  //初始化led闪烁线程
  time_test_tid = rt_thread_create("Thread_Led Run",
                                   Thread_Time_Flash, RT_NULL,
                                   THREAD_STACK_SIZE,
                                   THREAD_PRIORITY, THREAD_TIMESLICE);
  if (time_test_tid != RT_NULL) {
    rt_thread_startup(time_test_tid);
  }


  /* Add your code here */
  for (;;) {// 任务主循环
    int res = main_loop();
    SWDT_FeedDog();
    rt_thread_yield();
    // 当返回值为正数时为标准退出程序。直接退出。为0时啥也不干。为负时有错且需要出发处理程序
    if (res > 0) {
      break;
    } else if (res < 0) {
      ;
    } else {
      ;
    }// min_loop返回值处理
  }  // 任务主循环
}

char itoa_buf[16];
int itoa(int n, char *str, int zero) {
  // 处理数据为0
  if (zero <= 0 && n == 0) {
    str[0] = '0';
    str[1] = '\0';
    return 1;
  } else if (n == 0) {
    int i = 0;
    for (int index = 0; index < zero; index++) {
      str[i++] = '0';
    }
    return i;
  }

  // 处理非零
  // 先处理绝对值部分
  int tmp, i = 0;
  if (n < 0) {
    tmp = -n;
  } else {
    tmp = n;
  }
  // 假设str指向的数组至少有INT_MAX的位数加1个字符的空间
  // 在实际应用中，应该根据具体需求分配足够的空间
  char buf[12];
  do {
    buf[i++] = '0' + tmp % 10;// 取最低位的数字并转换为字符
    tmp /= 10;                // 去掉已经转换的最低位
  } while (tmp > 0);

  if (zero > 0 && i < zero) {
    for (int index = 0; index < zero - i; index++) {
      buf[i++] = '0';
    }
  }
  // 处理负数问题
  if (n < 0) {
    buf[i++] = '-';
  }

  for (int index = 0; index < i; index++) {
    str[index] = buf[i - index - 1];
  }

  str[i] = '\0';// 添加字符串结束符
  return i;
}

void uint8ToHexString(uint8_t value, char *hex_str) {
  static const char *hex_digits = "0123456789ABCDEF";
  hex_str[0] = hex_digits[(value >> 4) & 0x0F];// 高4位
  hex_str[1] = hex_digits[value & 0x0F];       // 低4位
}

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
